package battle_system

import (
	"confs/gen/common"
	"game/app/actors"
	"game/app/actors/schemas"
	"game/app/systems/move_system"
	"gos/bases/time_tools"

	"gitlab.outer.staruniongame.com/share/agent-common/logger"
)

func init() {
	actors.RegisterBattleTicker("battle_update", Battles.TickerBattleRefresh)
}

// BattleSystem 战斗系统
type BattleSystem struct{}

type IBattleSystem interface {
	TickerBattleRefresh(state *schemas.MoveState) error
	HasBattle(state *schemas.MoveState, attackerId, defenderId int64) bool
	CreateBattle(state *schemas.MoveState, attacker *common.BattleTroop, defender *common.BattleTroop, reason common.BattleCreateReason) (bool, *schemas.Battle)
	DestoryBattle(state *schemas.MoveState, a *schemas.BattleEntity, b *schemas.BattleEntity)
	OnDestoryBattle(state *schemas.MoveState, a *schemas.BattleEntity, b *schemas.BattleEntity, stop bool)
	StopBattle(state *schemas.MoveState, id int64)
}

var Battles IBattleSystem = BattleSystem{}

// TickerBattleRefresh 刷新战斗
func (s BattleSystem) TickerBattleRefresh(state *schemas.MoveState) error {
	state.ClearDestoryBattle()
	state.ClearDestoryLossTroop()
	battleCount := 0
	timeOutCount := 0
	state.Battles.Range(func(k, v interface{}) bool {
		battle := v.(*schemas.Battle)
		if battle.IsBattle {
			battleCount++
		} else {
			timeOutCount++
		}

		BattleRound.RoundUpdate(state, battle)
		return true
	})

	if time_tools.Now().Unix() >= state.CurTime+5 {
		state.CurTime = time_tools.Now().Unix()
		//logger.WARN("当前正在战斗数量:", battleCount, " 延时销毁战斗数量:", timeOutCount, " 追击的数量:", len(state.AiTargetBattleEntities))
	}

	BattlerSettle.SettleLossTroop(state)
	BattlerSettle.SettleBattleEnd(state)
	return nil
}

func (s BattleSystem) makeBattleKey(a int64, b int64) schemas.BattleKey {
	battleKey := schemas.BattleKey{
		A: a,
		B: b,
	}

	if battleKey.A > battleKey.B {
		battleKey.A = b
		battleKey.B = a
	}
	return battleKey
}

// CheckBattle 检查战斗
func (s BattleSystem) CheckBattle(state *schemas.MoveState, attacker *common.BattleTroop, defender *common.BattleTroop) bool {
	var soldierNum int32
	soldierNum = 0

	for _, army := range attacker.Soldiers {
		for _, soldier := range army.Soldiers {
			soldierNum += soldier
		}
	}

	if soldierNum <= 0 {
		return false
	}

	soldierNum = 0
	for _, army := range defender.InitSoldiers {
		for _, soldier := range army.Soldiers {
			soldierNum += soldier
		}
	}
	return soldierNum > 0
}

// HasBattle 战斗是否存在
func (s BattleSystem) HasBattle(state *schemas.MoveState, a, b int64) bool {
	attacker := state.GetBattleEntity(a)
	if attacker == nil {
		return false
	}

	if attacker != nil && attacker.IsDead {
		logger.WARN("A 死亡不能创建战斗:", attacker.Id)
		return true
	}

	defender := state.GetBattleEntity(b)
	if defender == nil {
		return false
	}

	if defender != nil && defender.IsDead {
		logger.WARN("B 死亡不能创建战斗:", defender.Id)
		return true
	}

	battleKey := s.makeBattleKey(a, b)
	battle := state.GetBattle(battleKey)
	if battle != nil {
		return true
	} else {
		return false
	}
}

func (s BattleSystem) InitBattle(state *schemas.MoveState, attacker *common.BattleTroop, defender *common.BattleTroop) bool {
	if attacker.Type == common.BattleEntityType_BattlePlayer {
		entity := move_system.Move.FindAndUpdate(state, attacker.Id)
		if entity == nil {
			return false
		}

		attacker.Position = entity.CurPos.ToVector2D()
		attacker.Direction = entity.Direction.ToVector2D()
	}

	if defender.Type == common.BattleEntityType_BattlePlayer {
		targetEntity := move_system.Move.FindAndUpdate(state, defender.Id)
		if targetEntity == nil {
			return false
		}
		defender.Position = targetEntity.CurPos.ToVector2D()
		defender.Direction = targetEntity.Direction.ToVector2D()
	}
	return true
}

// CreateBattle 创建战斗
func (s BattleSystem) CreateBattle(state *schemas.MoveState, attacker *common.BattleTroop, defender *common.BattleTroop, reason common.BattleCreateReason) (bool, *schemas.Battle) {
	if !s.InitBattle(state, attacker, defender) {
		return false, nil
	}

	if !s.CheckBattle(state, attacker, defender) {
		return false, nil
	}

	var a *schemas.BattleEntity
	var b *schemas.BattleEntity

	a = state.GetBattleEntity(attacker.Id)
	if a == nil {
		a = schemas.NewBattleEntity(attacker)
	}

	b = state.GetBattleEntity(defender.Id)
	if b == nil {
		b = schemas.NewBattleEntity(defender)
	}

	battleKey := s.makeBattleKey(a.Id, b.Id)
	battle := state.GetBattle(battleKey)
	if battle != nil {
		return true, battle
	}

	battle = schemas.NewBattle(state, battleKey, a, b)
	state.AddBattleId(battle.BattleId, battle)
	state.AddBattle(battleKey, battle)

	state.AddBattleEntityId(a.Id, battle.Key, battle)
	state.AddBattleEntityId(b.Id, battle.Key, battle)

	state.AddBattleEntities(a.Id, a)
	state.AddBattleEntities(b.Id, b)

	BattleRound.Start(state, battle)
	return true, battle
}

// OnDestoryBattle 被动销毁战斗事件
func (s BattleSystem) OnDestoryBattle(state *schemas.MoveState, a *schemas.BattleEntity, b *schemas.BattleEntity, stop bool) {
	// logger.WARN("被动销毁战斗事件对象:", a.Id, b.Id)
	battleKey := s.makeBattleKey(a.Id, b.Id)
	battle := state.GetBattle(battleKey)
	if battle != nil && !battle.IsBattle {
		BattleRound.OnDestory(state, battle, stop)
	} else {
		logger.ERR("被动销毁战斗事件失败:", battleKey)
	}
}

// DestoryBattle 销毁战斗
func (s BattleSystem) DestoryBattle(state *schemas.MoveState, a *schemas.BattleEntity, b *schemas.BattleEntity) {
	// logger.WARN("销毁战斗对象:", a.Id, b.Id)
	battleKey := s.makeBattleKey(a.Id, b.Id)
	battle := state.GetBattle(battleKey)
	if battle != nil && !battle.IsBattle {
		state.DeleteBattleEntityId(a.Id, battle.Key)
		state.DeleteBattleEntityId(b.Id, battle.Key)

		state.DeleteBattleEntities(a.Id, a)
		state.DeleteBattleEntities(b.Id, b)

		state.DeleteBattle(battle.Key)
		state.DeleteBattleId(battle.BattleId)
	} else {
		logger.ERR("销毁战斗失败:", battleKey)
	}
}

// StopBattle 主动停止战斗
func (s BattleSystem) StopBattle(state *schemas.MoveState, id int64) {
	entity := state.GetBattleEntity(id)
	if entity == nil {
		return
	}

	BattleRound.RoundStop(state, id, false)
	BattlerSettle.SettleBattleEnd(state)
	state.ClearDestoryBattle()
}

// DecideBattleType
func (s BattleSystem) DecideBattleType(state *schemas.MoveState, a *schemas.BattleEntity, b *schemas.BattleEntity) {

}
